package com.mf.service.impl;

import com.mf.entity.RecommendCode;
import com.mf.entity.TapePurchaseHistory;
import com.mf.entity.code.*;
import com.mf.mapper.TapePurchaseHistoryMapper;
import com.mf.mapper.code.*;
import com.mf.service.code.ICodeService;
import com.mf.service.IHomeService;
import com.mf.service.ITapePurchaseHistoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.utils.CCICalculator;
import com.mf.utils.CalculateKDJ;
import com.mf.vo.KDJVo;
import com.mf.vo.MACD.MACDVo;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * <p>
 * 收盘后推送的代买入历史股票代码 服务实现类
 * </p>
 *
 * @author mf
 * @since 2024-05-12
 */
@Service
public class TapePurchaseHistoryServiceImpl extends ServiceImpl<TapePurchaseHistoryMapper, TapePurchaseHistory> implements ITapePurchaseHistoryService {

    @Resource
    private ICodeService codeService;

    @Resource
    private IHomeService homeService;

    @Resource
    private Code000Mapper code000Mapper;

    @Resource
    private Code001Mapper code001Mapper;

    @Resource
    private Code002AMapper code002AMapper;

    @Resource
    private Code002BMapper code002BMapper;
    @Resource
    private Code003Mapper code003Mapper;
    @Resource
    private Code300AMapper code300AMapper;
    @Resource
    private Code300BMapper code300BMapper;
    @Resource
    private Code301Mapper code301Mapper;
    @Resource
    private Code600AMapper code600AMapper;
    @Resource
    private Code600BMapper code600BMapper;
    @Resource
    private Code601Mapper code601Mapper;
    @Resource
    private Code603Mapper code603Mapper;
    @Resource
    private Code605Mapper code605Mapper;
    @Resource
    private Code688Mapper code688Mapper;
    @Resource
    private Code689Mapper code689Mapper;
    @Resource
    private TapePurchaseHistoryMapper tapePurchaseHistoryMapper;

    /**
     * 获取macd相关指标
     */
    public MACDVo getMacdVo(List<RecommendCode> codeList) {
        final MACDVo macdVo = new MACDVo();
        // 获取k线图
        double[][] k = homeService.getKLine(codeList);
        macdVo.setK(k);
        macdVo.setDm(codeList.get(0).getDm());

        // 设置kdj指标
        macdVo.setKdj(CalculateKDJ.getKDJ(macdVo));
        // 获取cci
        final List<Double> cciList = CCICalculator.calculateCCI(codeList, 14);
        macdVo.setCci(cciList);
        return macdVo;
    }

    private void addHistoryCode(List<RecommendCode> recommendCodes) {
        MACDVo macdVo = getMacdVo(recommendCodes);
        final List<KDJVo> kdj = macdVo.getKdj();

        final List<Double> cci = macdVo.getCci();

        if (null == kdj || null == cci) {
            return;
        }

        // k线
        double[][] k = macdVo.getK();
        int size = kdj.size() - 1;
        // 如果 k 大于等于 j 线 10 那么j线不能大于20 (快接近死叉)
        boolean a1 = kdj.get(size).getK() - kdj.get(size).getJ() < 5 && kdj.get(size).getK() < 22;

        // 如果j线大于k线 10  那么j线不能小于20 (已经死叉)
        if (kdj.get(size).getJ() - kdj.get(size).getK() > 5 && kdj.get(size).getK() < 25) {
            a1 = true;
        }

        // kdj中的j线 必须大于前一天的
        boolean a3 = kdj.get(size).getJ() > kdj.get(size - 1).getJ();


        // cci大于前一天的 并且 前一天的cci大于前前天的cci
        boolean a2 = cci.get(size) > cci.get(size - 1) &&  cci.get(size - 1) >  cci.get(size - 2);
        // 当天的收盘加和前9天对比必须有一天小于收盘价5%
        boolean a4 = false;
        for (int i = 0; i < 9; i++) {
            if (k[size][1] < k[size - i][1] * 1.10) {
                a4 = true;
                break;
            }
        }

        // 如果


        if (a1 && a2 && a3 && a4) {
            final TapePurchaseHistory purchaseHistory = new TapePurchaseHistory();
            purchaseHistory.setCode(macdVo.getDm());
            tapePurchaseHistoryMapper.insert(purchaseHistory);
        }
    }

    @Override
    public void calculatedBuyIn() {
        calculateCode000();
        System.out.println("000计算完成");
        calculateCode001();
        System.out.println("001计算完成");
        calculateCode002A();
        System.out.println("002A计算完成");
        calculateCode002B();
        System.out.println("002B计算完成");
        calculateCode003();
        System.out.println("003计算完成");
        calculateCode300A();
        System.out.println("300A计算完成");
        calculateCode300B();
        System.out.println("300B计算完成");
        calculateCode301();
        System.out.println("301计算完成");
        calculateCode600A();
        System.out.println("600A计算完成");
        calculateCode600B();
        System.out.println("600B计算完成");
        calculateCode601();
        System.out.println("601计算完成");
        calculateCode603();
        System.out.println("603计算完成");
        calculateCode605();
        System.out.println("605计算完成");
        System.out.println("所有计算完成");
    }

    private void calculateCode000() {
        List<Code000> code000s = code000Mapper.selectList(null);
        Map<String, List<Code000>> collect1 = code000s.stream().collect(Collectors.groupingBy(Code000::getDm));
        // 获取code
        for (Map.Entry<String, List<Code000>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code000 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                // 添加记录
                addHistoryCode(recommendCodes);

            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode001() {
        List<Code001> code001s = code001Mapper.selectList(null);
        Map<String, List<Code001>> collect1 = code001s.stream().collect(Collectors.groupingBy(Code001::getDm));
        for (Map.Entry<String, List<Code001>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code001 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode002A() {
        List<Code002A> code002As = code002AMapper.selectList(null);
        Map<String, List<Code002A>> collect1 = code002As.stream().collect(Collectors.groupingBy(Code002A::getDm));
        for (Map.Entry<String, List<Code002A>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code002A code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode002B() {
        List<Code002B> code002Bs = code002BMapper.selectList(null);
        Map<String, List<Code002B>> collect1 = code002Bs.stream().collect(Collectors.groupingBy(Code002B::getDm));
        for (Map.Entry<String, List<Code002B>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code002B code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode003() {
        List<Code003> code003s = code003Mapper.selectList(null);
        Map<String, List<Code003>> collect1 = code003s.stream().collect(Collectors.groupingBy(Code003::getDm));
        for (Map.Entry<String, List<Code003>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code003 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode300A() {
        List<Code300A> code300As = code300AMapper.selectList(null);
        Map<String, List<Code300A>> collect1 = code300As.stream().collect(Collectors.groupingBy(Code300A::getDm));
        for (Map.Entry<String, List<Code300A>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code300A code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode300B() {
        List<Code300B> code300Bs = code300BMapper.selectList(null);
        Map<String, List<Code300B>> collect1 = code300Bs.stream().collect(Collectors.groupingBy(Code300B::getDm));
        for (Map.Entry<String, List<Code300B>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code300B code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode301() {
        List<Code301> code301s = code301Mapper.selectList(null);
        Map<String, List<Code301>> collect1 = code301s.stream().collect(Collectors.groupingBy(Code301::getDm));
        for (Map.Entry<String, List<Code301>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code301 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode600A() {
        List<Code600A> code600As = code600AMapper.selectList(null);
        Map<String, List<Code600A>> collect1 = code600As.stream().collect(Collectors.groupingBy(Code600A::getDm));
        for (Map.Entry<String, List<Code600A>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code600A code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode600B() {
        List<Code600B> code600Bs = code600BMapper.selectList(null);
        Map<String, List<Code600B>> collect1 = code600Bs.stream().collect(Collectors.groupingBy(Code600B::getDm));
        for (Map.Entry<String, List<Code600B>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code600B code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 601计算
     */
    private void calculateCode601() {
        List<Code601> code601s = code601Mapper.selectList(null);
        Map<String, List<Code601>> collect1 = code601s.stream().collect(Collectors.groupingBy(Code601::getDm));
        for (Map.Entry<String, List<Code601>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code601 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }


    private void calculateCode603() {
        List<Code603> code603s = code603Mapper.selectList(null);
        Map<String, List<Code603>> collect1 = code603s.stream().collect(Collectors.groupingBy(Code603::getDm));
        for (Map.Entry<String, List<Code603>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code603 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 605计算
     */
    private void calculateCode605() {
        List<Code605> code605s = code605Mapper.selectList(null);
        Map<String, List<Code605>> collect1 = code605s.stream().collect(Collectors.groupingBy(Code605::getDm));
        for (Map.Entry<String, List<Code605>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code605 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode688() {
        List<Code688> code688s = code688Mapper.selectList(null);
        Map<String, List<Code688>> collect1 = code688s.stream().collect(Collectors.groupingBy(Code688::getDm));
        for (Map.Entry<String, List<Code688>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code688 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void calculateCode689() {
        List<Code689> code689s = code689Mapper.selectList(null);
        Map<String, List<Code689>> collect1 = code689s.stream().collect(Collectors.groupingBy(Code689::getDm));
        for (Map.Entry<String, List<Code689>> entry : collect1.entrySet()) {
            try {
                List<RecommendCode> recommendCodes = new ArrayList<>();
                for (Code689 code : entry.getValue()) {
                    RecommendCode recommendCode = new RecommendCode();
                    BeanUtils.copyProperties(recommendCode, code);
                    recommendCodes.add(recommendCode);
                }
                addHistoryCode(recommendCodes);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

}
